package sqlstore

import (
	"fmt"
	"github.com/astaxie/beego"
	"github.com/jmoiron/sqlx"
	"reflect"
	"yikexing.com.cn/wyws/bus"
)

type dbTransactionFun func(tx *ThtfTx) error

type dbTranscationFunWithData func(tx *ThtfTx, datas map[string]interface{}) error

type ThtfTx struct {
	*sqlx.Tx
	events []interface{}
}

func (tx *ThtfTx) publishAfterCommit(msg interface{}) {
	beego.Debug(fmt.Sprintf("add message to event %s", msg))
	beego.Debug(fmt.Sprintf("the message type is %s", reflect.TypeOf(msg)))
	tx.events = append(tx.events, msg)
}

func InTransactionWithData(callback dbTranscationFunWithData, datas map[string]interface{}) error {

	var err error
	currentDB, err := GetDB(GetActiveDbName())
	if err != nil {
		return err
	}

	tx, err := currentDB.Beginx()

	tfthTx := ThtfTx{Tx: tx}

	if err != nil {
		return err
	}

	err = callback(&tfthTx, datas)

	if err != nil {
		tfthTx.Rollback()
		return err
	} else if err = tfthTx.Commit(); err != nil {
		return err
	}

	if len(tfthTx.events) > 0 {
		for _, e := range tfthTx.events {
			beego.Debug(fmt.Sprintf("will send post event %s", e))
			if err = bus.DispatchWithDataStack(e, datas); err != nil {
				beego.Error(fmt.Sprintf("Failed to publish event after commit. %s", err.Error()))
			}
		}
	}

	return nil
}

func InTransaction(callback dbTransactionFun) error {
	var err error
	currentDB, err := GetDB(GetActiveDbName())
	if err != nil {
		return err
	}

	tx, err := currentDB.Beginx()

	tfthTx := ThtfTx{Tx: tx}

	if err != nil {
		return err
	}

	err = callback(&tfthTx)

	if err != nil {
		tfthTx.Rollback()
		return err
	} else if err = tfthTx.Commit(); err != nil {
		return err
	}

	if len(tfthTx.events) > 0 {
		for _, e := range tfthTx.events {
			beego.Debug(fmt.Sprintf("will send post event %s", e))
			if err = bus.Dispatch(e); err != nil {
				beego.Error(fmt.Sprintf("Failed to publish event after commit. %s", err.Error()))
			}
		}
	}

	return nil
}
